//
//  PPActivityCommitManager.m
//  pickpic
//
//  Created by Jinxiao on 10/8/16.
//  Copyright © 2016 MicroDream. All rights reserved.
//

#import "PPActivityCommitManager.h"

#import "PPActivityCommitRecord.h"

@interface PPActivityCommitManager ()

@property (readwrite, nonatomic, assign) BOOL needsCommit;

@end

@implementation PPActivityCommitManager

+ (instancetype)sharedInstance {
    static id instance;
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        instance = self.new;
    });

    return instance;
}

- (void)commitIfNeeded {
    static BOOL committing;


    NSString *userID = DGCurrentAccount.userID;

    if(userID.length == 0) {
        return;
    }


    if(committing) {
        _needsCommit = YES;

        return;
    }

    committing = YES;

    dispatch_group_t group = dispatch_group_create();


    NSArray <PPActivityCommitRecord *> *records = [PPActivityCommitRecord where:@{@"userID" : userID, @"committing" : @(NO)}];

    [records enumerateObjectsUsingBlock:^(PPActivityCommitRecord *_Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) {

        obj.committing = @(YES);

        switch(obj.type.integerValue) {

            case PPActivityCommitTypeLikeAlbum: {

                NSManagedObjectID *objectID = obj.objectID;

                dispatch_group_enter(group);
                [PPNetworkService likeWithType:@1 ID:obj.targetID version:obj.version callback:^(id data, NSError *error) {

                    if(error == nil || ![AFNetworkReachabilityManager sharedManager].reachable) {
                        PPActivityCommitRecord *record = [[NSManagedObjectContext threadObjectContext] objectWithID:objectID];
                        [record delete];
                        [record.managedObjectContext saveContext];
                    }

                    dispatch_group_leave(group);

                }];

                break;
            }

            case PPActivityCommitTypeUnlikeAlbum: {

                NSManagedObjectID *objectID = obj.objectID;

                dispatch_group_enter(group);
                [PPNetworkService unLikeWithType:@1 ID:obj.targetID version:obj.version callback:^(id data, NSError *error) {

                    if(error == nil || ![AFNetworkReachabilityManager sharedManager].reachable) {
                        PPActivityCommitRecord *record = [[NSManagedObjectContext threadObjectContext] objectWithID:objectID];
                        [record delete];
                        [record.managedObjectContext saveContext];
                    }

                    dispatch_group_leave(group);

                }];

                break;
            }

            case PPActivityCommitTypeFavoriteAlbum: {

                NSManagedObjectID *objectID = obj.objectID;

                dispatch_group_enter(group);
                [PPNetworkService favouriteAlbumID:obj.targetID version:obj.version callback:^(id data, NSError *error) {

                    if(error == nil || ![AFNetworkReachabilityManager sharedManager].reachable) {
                        PPActivityCommitRecord *record = [[NSManagedObjectContext threadObjectContext] objectWithID:objectID];
                        [record delete];
                        [record.managedObjectContext saveContext];
                    }

                    dispatch_group_leave(group);

                }];

                break;
            }

            case PPActivityCommitTypeUnfavoriteAlbum: {

                NSManagedObjectID *objectID = obj.objectID;

                dispatch_group_enter(group);
                [PPNetworkService unFavouriteAlbumID:obj.targetID version:obj.version callback:^(id data, NSError *error) {

                    if(error == nil || ![AFNetworkReachabilityManager sharedManager].reachable) {
                        PPActivityCommitRecord *record = [[NSManagedObjectContext threadObjectContext] objectWithID:objectID];
                        [record delete];
                        [record.managedObjectContext saveContext];
                    }

                    dispatch_group_leave(group);

                }];

                break;
            }



            case PPActivityCommitTypeLikeImage: {

                NSManagedObjectID *objectID = obj.objectID;

                dispatch_group_enter(group);
                [PPNetworkService likeWithType:@2 ID:obj.targetID version:nil callback:^(id data, NSError *error) {

                    if(error == nil || ![AFNetworkReachabilityManager sharedManager].reachable) {
                        PPActivityCommitRecord *record = [[NSManagedObjectContext threadObjectContext] objectWithID:objectID];
                        [record delete];
                        [record.managedObjectContext saveContext];
                    }

                    dispatch_group_leave(group);

                }];

                break;
            }

            case PPActivityCommitTypeUnlikeImage: {

                NSManagedObjectID *objectID = obj.objectID;

                dispatch_group_enter(group);
                [PPNetworkService unLikeWithType:@2 ID:obj.targetID version:nil callback:^(id data, NSError *error) {

                    if(error == nil || ![AFNetworkReachabilityManager sharedManager].reachable) {
                        PPActivityCommitRecord *record = [[NSManagedObjectContext threadObjectContext] objectWithID:objectID];
                        [record delete];
                        [record.managedObjectContext saveContext];
                    }
                    
                    dispatch_group_leave(group);
                    
                }];
                
                break;
            }


            default: break;

        }
    }];


    [[NSManagedObjectContext threadObjectContext] saveContext];



    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        committing = NO;

        if(_needsCommit) {
            _needsCommit = NO;

            [self commitIfNeeded];
        }
    });
}

- (void)offlineCommitWithCommitType:(PPActivityCommitType)type targetID:(NSNumber *)targetID version:(NSString *)version {

    NSString *userID = DGCurrentAccount.userID;

    PPActivityCommitType oppositeType = PPActivityCommitTypeUnknown;

    switch(type) {
        case PPActivityCommitTypeLikeAlbum: oppositeType = PPActivityCommitTypeUnlikeAlbum; break;
        case PPActivityCommitTypeUnlikeAlbum: oppositeType = PPActivityCommitTypeLikeAlbum; break;
        case PPActivityCommitTypeFavoriteAlbum: oppositeType = PPActivityCommitTypeUnfavoriteAlbum; break;
        case PPActivityCommitTypeUnfavoriteAlbum: oppositeType = PPActivityCommitTypeFavoriteAlbum; break;

        case PPActivityCommitTypeLikeImage: oppositeType = PPActivityCommitTypeUnlikeImage; break;
        case PPActivityCommitTypeUnlikeImage: oppositeType = PPActivityCommitTypeLikeImage; break;

        default: break;
    }

    PPActivityCommitRecord *oppositeRecord = [PPActivityCommitRecord find:@{@"userID" : userID, @"type" : @(oppositeType), @"targetID": targetID}];

    // 如果有未处理的“取消赞”
    if(oppositeRecord != nil) {

        // 如果前一个“取消赞”的请求刚发出去 还没返回，则什么也不做
        if(oppositeRecord.committing.boolValue) {
            return;
        }
        // 如果前一个“取消赞”的请求刚出去 但是返回失败，说明前一个“取消赞”没有提交成功，此时album的状态还是赞，所以不需要提交服务器，只需要取消前后两次提交，并且本地修改状态即可
        else {
            [oppositeRecord delete];
            [oppositeRecord.managedObjectContext saveContext];
        }
    } else {
        PPActivityCommitRecord *record = [PPActivityCommitRecord create];
        record.userID = userID;
        record.type = @(type);
        record.targetID = targetID;
        record.committing = @(NO);
        record.version = version;
        [record.managedObjectContext saveContext];
    }

    [self commitIfNeeded];
}

- (void)offlineLikeAlbumWithAlbumID:(PPAlbumID)albumID {
    [self offlineLikeAlbumWithAlbumID:albumID version:nil];
}

- (void)offlineLikeAlbumWithAlbumID:(PPAlbumID)albumID version:(NSString *)version {
    [self offlineCommitWithCommitType:PPActivityCommitTypeLikeAlbum targetID:@(albumID) version:version];
}

- (void)offlineUnlikeAlbumWithAlbumID:(PPAlbumID)albumID {
    [self offlineUnlikeAlbumWithAlbumID:albumID version:nil];
}

- (void)offlineUnlikeAlbumWithAlbumID:(PPAlbumID)albumID version:(NSString *)version {
    [self offlineCommitWithCommitType:PPActivityCommitTypeUnlikeAlbum targetID:@(albumID) version:version];
}

- (void)offlineFavoriteAlbumWithAlbumID:(PPAlbumID)albumID {
    [self offlineFavoriteAlbumWithAlbumID:albumID version:nil];
}

- (void)offlineFavoriteAlbumWithAlbumID:(PPAlbumID)albumID version:(NSString *)version {
    [self offlineCommitWithCommitType:PPActivityCommitTypeFavoriteAlbum targetID:@(albumID) version:version];
}

- (void)offlineUnfavoriteAlbumWithAlbumID:(PPAlbumID)albumID {
    [self offlineUnfavoriteAlbumWithAlbumID:albumID version:nil];
}

- (void)offlineUnfavoriteAlbumWithAlbumID:(PPAlbumID)albumID version:(NSString *)version {
    [self offlineCommitWithCommitType:PPActivityCommitTypeUnfavoriteAlbum targetID:@(albumID) version:version];
}


- (void)offlineLikeImageWithImageID:(PPAlbumImageID)imageID {
    [self offlineCommitWithCommitType:PPActivityCommitTypeLikeImage targetID:@(imageID) version:nil];
}

- (void)offlineUnlikeImageWithImageID:(PPAlbumImageID)imageID {
    [self offlineCommitWithCommitType:PPActivityCommitTypeUnlikeImage targetID:@(imageID) version:nil];
}

@end
